//
//  DBStorageService.m
//  MiniWeChat
//
//  Created by ByteDance on 2025/6/26.
//

#import <FMDB/FMDB.h>
#import "DBStorageService.h"

@interface DBStorageService ()

@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
@property (nonatomic, strong) UserModel *currentUser;

@end

@implementation DBStorageService

// 单例模式
+ (instancetype)sharedInstance {
    static DBStorageService *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setupDatabase];
    }
    return self;
}

- (void)setupDatabase {
    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *dbPath = [documentsPath stringByAppendingPathComponent:@"miniwechat.db"];
    
    self.dbQueue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"CREATE TABLE IF NOT EXISTS User (id TEXT PRIMARY KEY, nickname TEXT, avatar TEXT, phone TEXT, gender INTEGER, signature TEXT, extra TEXT)"];
        
        [db executeUpdate:@"CREATE TABLE IF NOT EXISTS Conversation (id TEXT PRIMARY KEY, type INTEGER, nickname TEXT, avatar TEXT, last_msg_id TEXT, last_msg_content TEXT, last_msg_time INTEGER, unread_count INTEGER, is_top INTEGER, is_muted INTEGER)"];
        
        [db executeUpdate:@"CREATE TABLE IF NOT EXISTS Message (id TEXT PRIMARY KEY, conversation_id TEXT, type INTEGER, sender TEXT, content TEXT, media_path TEXT, media_duration INTEGER, media_size INTEGER, status INTEGER, time INTEGER)"];
    }];
}


// 用户相关实现
- (void)saveUser:(UserModel *)user {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"INSERT OR REPLACE INTO User (id, nickname, avatar, phone, gender, signature, extra) VALUES (?, ?, ?, ?, ?, ?, ?)",
         user.id, user.nickname, user.avatar, user.phone, @(user.gender), user.signature, user.extra];
    }];
}

- (void)saveCurrentUser:(UserModel *)user {
    self.currentUser = user;
    
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"INSERT OR REPLACE INTO User (id, nickname, avatar, phone, gender, signature, extra) VALUES (?, ?, ?, ?, ?, ?, ?)",
         user.id, user.nickname, user.avatar, user.phone, @(user.gender), user.signature, user.extra];
    }];
    
    // 保存到 UserDefaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:user.id forKey:@"uid"];
    [defaults synchronize];
}

- (UserModel *)currentUser {
    // 方案一：缓存 uid 后续从数据库中查询
    // 方案二：缓存整个用户数据 数据库中也保存当前用户数据 但需要确保数据唯一性
    // 方案三：缓存整个用户数据 数据库不保存当前用户数据
    if (!_currentUser) {
        // 从 UserDefaults 获取 uid
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *uid = [defaults objectForKey:@"uid"];
        if (uid) {
            // 从数据库中根据 uid 获取用户信息
            [self.dbQueue inDatabase:^(FMDatabase *db) {
                // TODO 1. 是否存在 SQL 注入问题 2. 即使存在 是否有必要避免（SQLite 文件都是公开的）
                FMResultSet *rs = [db executeQuery:@"SELECT * FROM User WHERE id = ?", uid];
                if ([rs next]) {
                    UserModel *user = [[UserModel alloc] init];
                    user.id = [rs stringForColumn:@"id"];
                    user.nickname = [rs stringForColumn:@"nickname"];
                    user.avatar = [rs stringForColumn:@"avatar"];
                    user.phone = [rs stringForColumn:@"phone"];
                    user.gender = [rs intForColumn:@"gender"];
                    user.signature = [rs stringForColumn:@"signature"];
                    user.extra = [rs stringForColumn:@"extra"];
                    _currentUser = user;
                }
                [rs close];
            }];
        }
    }
    return _currentUser;
}

-(UserModel *)fetchUserById:(NSString *)id {
    __block UserModel *res = nil;
    // 从数据库中根据 id 获取用户信息
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        FMResultSet *rs = [db executeQuery:@"SELECT * FROM User WHERE id = ?", id];
        if ([rs next]) {
            UserModel *user = [[UserModel alloc] init];
            user.id = [rs stringForColumn:@"id"];
            user.nickname = [rs stringForColumn:@"nickname"];
            user.avatar = [rs stringForColumn:@"avatar"];
            user.phone = [rs stringForColumn:@"phone"];
            user.gender = [rs intForColumn:@"gender"];
            user.signature = [rs stringForColumn:@"signature"];
            user.extra = [rs stringForColumn:@"extra"];
            res = user;
        }
        [rs close];
    }];
    return res;
}

- (void)removeCurrentUser {
    // 移除 UserDefaults 缓存的信息以及内存中当前用户信息置空
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    _currentUser = nil;
}

// 聊天会话相关
- (void)fetchConversationById:(NSString *)id completion:(void(^)(ConversationModel *conversation, NSError *error))completion {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        FMResultSet *rs = [db executeQuery:@"SELECT * FROM Conversation WHERE id = ?", id];
        if ([rs next]) {
            ConversationModel *conversation = [[ConversationModel alloc] init];
            conversation.id = [rs stringForColumn:@"id"];
            conversation.type = [rs intForColumn:@"type"];
            if (completion) completion(conversation, nil);
        }
        [rs close];
    }];
}

- (void)saveConversation:(ConversationModel *)conversation {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"INSERT OR REPLACE INTO Conversation (id, type, nickname, avatar, last_msg_id, last_msg_content, last_msg_time, unread_count, is_top, is_muted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
         conversation.id, @(conversation.type), conversation.nickname, conversation.avatar, conversation.last_msg_id, conversation.last_msg_content, @(conversation.last_msg_time), @(conversation.unread_count), conversation.is_top, conversation.is_muted];
    }];
}

- (void)fetchConversationsByUid:(NSString *)uid completion:(void(^)(NSArray<ConversationModel *> *conversations, NSError *error))completion {
    // 本地保存的所有会话都是属于 uid （前提不同用户的用户数据进行隔离）
    NSLog(@"开始调用数据库获取数据");
    __block NSError *fetchError = nil;
    NSMutableArray<ConversationModel *> *conversations = [NSMutableArray array];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        
        // 执行查询
        FMResultSet *resultSet = [db executeQuery:@"SELECT * FROM Conversation ORDER BY last_msg_time DESC"];
        
        if (resultSet) {
            // 遍历结果集
            while ([resultSet next]) {
                ConversationModel *conversation = [[ConversationModel alloc] init];
                
                // 从结果集提取数据
                conversation.id = [resultSet stringForColumn:@"id"];
                conversation.type = [resultSet intForColumn:@"type"];
                conversation.nickname = [resultSet stringForColumn:@"nickname"];
                conversation.avatar = [resultSet stringForColumn:@"avatar"];
                conversation.last_msg_id = [resultSet stringForColumn:@"last_msg_id"];
                conversation.last_msg_content = [resultSet stringForColumn:@"last_msg_content"];
                conversation.last_msg_time = [resultSet intForColumn:@"last_msg_time"];
                conversation.unread_count = [resultSet intForColumn:@"unread_count"];
                conversation.is_top = [resultSet boolForColumn:@"is_top"];
                conversation.is_muted = [resultSet boolForColumn:@"is_muted"];
                
                [conversations addObject:conversation];
            }
            
            [resultSet close];
        } else {
            // 查询失败，创建错误对象
            fetchError = [NSError errorWithDomain:@"DataStorageErrorDomain"
                                             code:1003
                                         userInfo:@{ @"title": @"获取会话列表失败",
                                                     @"error": [db lastErrorMessage] }
            ];
        }
    }];
    NSLog(@"加载了 %lu 个结果", [conversations count]);
    if (completion) {
        completion([conversations copy], fetchError);
    }
}

- (NSArray<MessageModel *> *)fetchMessagesByReceiver:(NSString *)receiver completion:(void (^)(NSArray<MessageModel *> * _Nonnull, NSError * _Nonnull))completion {
    // 根据接收者用户主键获取本地所有消息（群聊为特殊好友）
    __block NSError *error = nil;
    NSMutableArray<MessageModel *> *messages = [NSMutableArray array];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        // 执行查询
        FMResultSet *rs = [db executeQuery:@"SELECT * FROM Message WHERE receiver = ?", receiver];
        if (!rs){
            error = [NSError errorWithDomain:@"DataStorageErrorDomain"
                                        code:1003
                                    userInfo:@{ @"title": @"获取会话消息失败",
                                                @"error": [db lastErrorMessage] }
            ];
        }
        else {
            while ([rs next]) {
                MessageModel *message = [[MessageModel alloc] init];
                message.id = [rs stringForColumn:@"id"];
                message.sender =  [rs stringForColumn:@"sender"];
                message.sender =  [rs stringForColumn:@"sender"];
                message.sender =  [rs stringForColumn:@"sender"];
                message.sender =  [rs stringForColumn:@"sender"];
                message.sender =  [rs stringForColumn:@"sender"];
                message.sender =  [rs stringForColumn:@"sender"];
                
                [messages addObject:message];
            }
            [rs close];
        }
    }];
    if (completion)  completion([messages copy], error);
    return messages;
}

- (NSArray<MessageModel *> *)fetchMessagesByConversationId:(NSString *)conversation_id {
    NSMutableArray<MessageModel *> *messages = [NSMutableArray array];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        // 执行查询
        FMResultSet *rs = [db executeQuery:@"SELECT * FROM Message WHERE conversation_id = ?", conversation_id];
        if (rs) {
            while ([rs next]) {
                MessageModel *message = [[MessageModel alloc] init];
                message.id = [rs stringForColumn:@"id"];
                message.conversation_id = [rs stringForColumn:@"conversation_id"];
                message.type =  [rs intForColumn:@"type"];
                message.sender = [rs stringForColumn:@"sender"];
//                message.receiver = [rs stringForColumn:@"receiver"];
                message.content = [rs stringForColumn:@"content"];
                message.media_path = [rs stringForColumn:@"media_path"];
                message.media_duration = [rs intForColumn:@"media_duration"];
                message.media_size = [rs intForColumn:@"media_size"];
                message.status = [rs intForColumn:@"status"];
                message.time = [rs intForColumn:@"time"];
                
                [messages addObject:message];
            }
            [rs close];
        }
    }];
    return messages;
}

- (void)saveMessage:(MessageModel *)message {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"INSERT OR REPLACE INTO Message (id, conversation_id, type, sender, content, media_path, media_duration, media_size, status, time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", message.id, message.conversation_id, @(message.type), message.sender, message.content, message.media_path, @(message.media_duration), @(message.media_size), @(message.media_size), @(message.status), @(message.time)];
    }];
}

@end
